﻿using UnityEngine;
using UnityEngine.Rendering;

public partial class CameraRenderer
{
    private ScriptableRenderContext contex;
    private Camera camera;

    private static ShaderTagId unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit");
    private const string bufferName = "Render Camera";

    private CommandBuffer buffer;
    private CullingResults cullingResults;

    public CameraRenderer()
    {
        this.buffer = new CommandBuffer {name = bufferName};
    }

    public void Render(ScriptableRenderContext cont, Camera cam)
    {
        this.contex = cont;
        this.camera = cam;

        PrepareBuffer();
        PrepareForSecondWindow();

        if (!Cull())
            return;

        Setup();

        DrawVisibleGeometry();
        DrawUnsupportedShaders();

        DrawGizmos();
        Submit();
    }

    private void Setup()
    {
        this.contex.SetupCameraProperties(this.camera);
        this.buffer.BeginSample(SampleName);
        CameraClearFlags flags = this.camera.clearFlags;
        this.buffer.ClearRenderTarget(flags <= CameraClearFlags.Depth, flags == CameraClearFlags.Color,
            flags == CameraClearFlags.Color ? camera.backgroundColor.linear : Color.clear);
        this.ExecuteBuffer();
    }

    private void DrawVisibleGeometry()
    {
        var sortingSetting = new SortingSettings(this.camera)
        {
            criteria = SortingCriteria.CommonOpaque
        };
        var drawingSetting = new DrawingSettings(unlitShaderTagId, sortingSetting);
        var filteringSetting = new FilteringSettings(RenderQueueRange.opaque); //渲染不透明队列

        //绘制物体
        this.contex.DrawRenderers(cullingResults, ref drawingSetting, ref filteringSetting);
        //绘制天空盒
        this.contex.DrawSkybox(this.camera);

        //绘制透明物体
        sortingSetting.criteria = SortingCriteria.CommonTransparent;
        drawingSetting.sortingSettings = sortingSetting;
        filteringSetting.renderQueueRange = RenderQueueRange.transparent;//渲染透明队列

        this.contex.DrawRenderers(cullingResults, ref drawingSetting, ref filteringSetting);
    }

    /// <summary>
    /// 裁剪不可见片段
    /// </summary>
    /// <returns></returns>
    private bool Cull()
    {
        if (this.camera.TryGetCullingParameters(out ScriptableCullingParameters parame))
        {
            cullingResults = this.contex.Cull(ref parame);
            return true;
        }

        return false;
    }

    private void Submit()
    {
        this.buffer.EndSample(SampleName);
        this.ExecuteBuffer();
        this.contex.Submit();
    }

    private void ExecuteBuffer()
    {
        this.contex.ExecuteCommandBuffer(this.buffer);
        this.buffer.Clear();
    }
}
